#ifndef QP_QF_HPP
#define QP_QF_HPP
#include "QActive.hpp"
#include "QEP.hpp"
#include "QFPort.hpp"
#include "QPSet.hpp"
#include "QTimeEvt.hpp"

namespace QP {

using QSubscrList = QPSet;

/// \brief QF services.
///
/// This class groups together QF services. It has only static members and
/// should not be instantiated.
class QF {
 public:
  //! get the current QF version number string of the form X.Y.Z
  static char const *getVersion(void) noexcept { return versionStr; }

  //! QF initialization.
  static void init(void);
  //! Publish-subscribe initialization.
  static void psInit(QSubscrList *const subscrSto, int maxSignal);

  //! Transfers control to QF to run the application.
  static int run(void);
  //! Startup QF callback.
  static void onStartup(void);
  //! Cleanup QF callback.
  static void onCleanup(void);
  //! Function invoked by the application layer to stop the QF
  //! application and return control to the OS/Kernel.
  static void stop(void);

  static void publish_(std::shared_ptr<const QEvt> &e);
  static void tick(void);

  /// \brief Returns true if all time events are inactive and false
  /// any time event is active.
  ///
  /// \note This function should be called in critical section.
  static bool noTimeEvtsActive(void);

  /// \brief This function returns the margin of the given event queue.
  ///
  /// This function returns the margin of the given event queue of an active
  /// object with priority \a prio. (QF priorities start with 1 and go up to
  /// #QF_MAX_ACTIVE.) The margin is the minimal number of free events
  /// encountered in the given queue since system startup.
  ///
  /// \note QF::getQueueMargin() is available only when the native QF event
  /// queue implementation is used. Requesting the queue margin of an unused
  /// priority level raises an assertion in the QF. (A priority level
  /// becomes used in QF after the call to the QF::add_() function.)
  static uint32_t getQueueMargin(uint8_t const prio);

  //! Register an active object to be managed by the framework
  static void add_(QActive *const a) noexcept;
  //! Remove the active object from the framework.
  static void remove_(QActive *const a) noexcept;
  //! array of registered active objects
  static QActive *active_[QF_MAX_ACTIVE + 1U];
  //! Thread routine for executing an active object @p act.
  static void thread_(QActive *act);

 private:
  friend class QActive;
  friend class QTimeEvt;
};

}  // namespace QP

#define TICK(dummy_) tick()
#define PUBLISH(e_, dummy_) publish(e_)

#endif  // QP_QF_HPP
